//package com.charley.icloud.aop;
//
//import com.alibaba.fastjson.JSON;
//import com.charley.icloud.common.response.result.ResponseHaveDataResult;
//import com.charley.icloud.common.response.result.ResponseResult;
//import com.charley.icloud.entity.SysLogEntity;
//import com.charley.icloud.service.LogService;
//import com.charley.icloud.service.SysUserService;
//import com.charley.icloud.table.entity.SysUser;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.annotation.AfterReturning;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Before;
//import org.aspectj.lang.annotation.Pointcut;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.core.NamedThreadLocal;
//import org.springframework.stereotype.Component;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//
//import javax.annotation.Resource;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.lang.reflect.Method;
//import java.util.Date;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.Objects;
//
///**
// * Spring AOP 实现日志管理
// * @author charley
// * @date 2024-04-16 14:30
// */
//@Aspect
//@Component
//@Slf4j
//public class SystemLogAspect {
//    Logger logger = LoggerFactory.getLogger(RequestLogAspect.class);
//
//    private static final ThreadLocal<Date> beginTimeThreadLocal = new NamedThreadLocal<>("System-Log-Recorder");
//
//    @Resource
//    private LogService logService;
//
//    @Resource
//    private SysUserService userService;
//
//    private HttpServletRequest request;
//
//
//    /**
//     * Controller层切点,注解方式
//     * 凡是添加了【@EnableApiLog】注解的类、方法都会记录日志
//     */
//    //@Pointcut("execution(* *..controller..*Controller*.*(..))")
//    @Pointcut("@annotation(com.charley.icloud.annotation.EnableApiLog)")
//    public void controllerAspect() {
//    }
//
//    /**
//     * 前置通知 (在方法执行之前返回)用于拦截Controller层记录用户的操作的开始时间
//     */
//    @Before("controllerAspect()")
//    public void doBefore() {
//        logger.info("SystemLogAspect -----》 doBefore() 方法执行了......");
//        //线程绑定变量（该数据只有当前请求的线程可见）
//        Date beginTime = new Date();
//        beginTimeThreadLocal.set(beginTime);
//        // 获取Request对象
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        assert attributes != null;
//        this.request = attributes.getRequest();
//    }
//
//    /**
//     * 后置通知(在方法执行之后并返回数据) 用于拦截Controller层无异常的操作
//     *
//     * @param joinPoint 切点
//     */
//    @AfterReturning(value = "controllerAspect()", returning = "methodResult")
//    public void after(JoinPoint joinPoint, Object methodResult) {
//        logger.info("SystemLogAspect -----》 after() 方法执行了......");
//
//        try {
//            String username;
//            String description = getControllerMethodInfo(joinPoint).get("description").toString();
//
//            //Map<String, String[]> requestParams = this.request.getParameterMap();
//            SysLogEntity log = new SysLogEntity();
//
//            //请求用户
//            //后台操作 (非登录)
//            if (Objects.equals(getControllerMethodInfo(joinPoint).get("type"), 0)) {
//                //后台操作请求(已登录)
//                SysUser user = userService.getLoginUser(request);
//                if (user != null) {
//                    username = user.getUsername();
//                    log.setUsername(username);
//                    log.setUserAccount(user.getAccount());
//                }
//            }
//            //日志标题
//            log.setName(description);
//            //日志类型
//            log.setLogType((int) getControllerMethodInfo(joinPoint).get("type"));
//            //日志请求url
//            log.setRequestUrl(request.getRequestURI());
//            //请求方式
//            log.setRequestType(request.getMethod());
//            //请求参数
//            Object[] args = joinPoint.getArgs();
//            for (Object arg : args) {
//                if (arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) {
//                    continue;
//                }
//                // 如果是登录接口
//                if (Objects.equals(getControllerMethodInfo(joinPoint).get("type"), 1)){
//                    if(arg instanceof AuthParams) {
//                        AuthParams params = (AuthParams) arg;
//                        params.setPassword(null);
//                    }else if(arg instanceof RegisterUser){
//                        RegisterUser params = (RegisterUser) arg;
//                        params.setPassword(null);
//                    }
//                }
//                log.setRequestParam(JSON.toJSON(arg).toString());
//            }
//            // 接口执行响应结果
//            log.setResponseRest(JSON.toJSON(methodResult).toString());
//            // 接口执行状态判断
//            if (methodResult instanceof ResponseHaveDataResult) {
//                ResponseHaveDataResult<?> result = (ResponseHaveDataResult<?>) methodResult;
//                if (!"0".equals(result.getResultCode())) {
//                    log.setRemark(1); // 失败
//                }
//            } else if (methodResult instanceof ResponseResult) {
//                ResponseResult result = (ResponseResult) methodResult;
//                if (!"0".equals(result.getResultCode())) {
//                    log.setRemark(1); // 失败
//                }
//            } else if (methodResult instanceof ResponsePage) {
//                ResponsePage<T> result = (ResponsePage<T>) methodResult;
//                if (!"0".equals(result.getResultCode())) {
//                    log.setRemark(1); // 失败
//                }
//            }
//
//            //其他属性
//            log.setIp(IpInfoUtil.getIpAddr(request));
//            log.setCreateBy("system");
//            log.setUpdateBy("system");
//            log.setCreateTime(new Date());
//            log.setUpdateTime(new Date());
//            log.setDelFlag(0);
//
//            //请求开始时间
//            long beginTime = beginTimeThreadLocal.get().getTime();
//            long endTime = System.currentTimeMillis();
//            //请求耗时
//            long logElapsedTime = endTime - beginTime;
//            log.setCostTime((int) logElapsedTime);
//
//            //持久化(存储到数据或者ES，可以考虑用线程池)
//            //logService.insert(log);
//            ThreadPoolUtil.getPool().execute(new SaveSystemLogThread(log, logService));
//        } catch (Exception e) {
//            log.error("AOP后置通知异常", e);
//        }
//    }
//
//    /**
//     * 保存日志至数据库
//     */
//    private static class SaveSystemLogThread implements Runnable {
//
//        private final SysLogEntity log;
//        private final LogService logService;
//
//        public SaveSystemLogThread(SysLogEntity esLog, LogService logService) {
//            this.log = esLog;
//            this.logService = logService;
//        }
//
//        @Override
//        public void run() {
//            logService.insert(log);
//        }
//    }
//
//    /**
//     * 获取注解中对方法的描述信息 用于Controller层注解
//     *
//     * @param joinPoint 切点
//     * @return 方法描述
//     * @throws Exception
//     */
//    public static Map<String, Object> getControllerMethodInfo(JoinPoint joinPoint) throws Exception {
//
//        Map<String, Object> map = new HashMap<>(16);
//        //获取目标类名
//        String targetName = joinPoint.getTarget().getClass().getName();
//        //获取方法名
//        String methodName = joinPoint.getSignature().getName();
//        //获取相关参数
//        Object[] arguments = joinPoint.getArgs();
//        //生成类对象
//        Class<?> targetClass = Class.forName(targetName);
//        //获取该类中的方法
//        Method[] methods = targetClass.getMethods();
//
//        String description;
//        int type;
//
//        for (Method method : methods) {
//            if (!method.getName().equals(methodName)) {
//                continue;
//            }
//            Class<?>[] clazzs = method.getParameterTypes();
//            if (clazzs.length != arguments.length) {
//                //比较方法中参数个数与从切点中获取的参数个数是否相同，原因是方法可以重载哦
//                continue;
//            }
//            description = method.getAnnotation(SystemLog.class).description();
//            type = method.getAnnotation(SystemLog.class).type().ordinal();
//            map.put("description", description);
//            map.put("type", type);
//        }
//        return map;
//    }
//
//}
